#include "LXCanObject.h"
LXCanMemery LXCanObject::datamemery;

void LXCanObject::value_read(uint8_t* value,uint8_t &length)
{
	length = value_len;
	for (int i = 0; i < value_len; i++)
	{
		value[i] = this->value_buff[i];
	}
}

uint8_t LXCanObject::value_write(uint8_t *value,uint8_t length)
{
	if(length != value_len)
		return 0;
	for (int i = 0; i < value_len; i++)
	{
		this->value_buff[i] = value[i];
	}
	return 1;
}
template <typename T>
e_LXCanDeviceStatus LXCanObject::value_read(T& resultValue)
{
	uint8_t *dptOriginValue = value_buff;
	uint8_t dptFormat = LXCanDPTIdToFormat[Dpt_ID];
	switch (dptFormat)
	{
	case LXCAN_DPT_FORMAT_B1:
	case LXCAN_DPT_FORMAT_B2:
	case LXCAN_DPT_FORMAT_B1U3:
	case LXCAN_DPT_FORMAT_A8:
	case LXCAN_DPT_FORMAT_U8:
	case LXCAN_DPT_FORMAT_V8:
	case LXCAN_DPT_FORMAT_B5N3:
		resultValue = (T)dptOriginValue[0];
		return LXCAN_DEVICE_OK; 
	case LXCAN_DPT_FORMAT_U16:
	case LXCAN_DPT_FORMAT_V16:
		resultValue = (T)((unsigned int)dptOriginValue[0] << 8);
		resultValue += (T)(dptOriginValue[1]);
		return LXCAN_DEVICE_OK;
		//		break;

	case LXCAN_DPT_FORMAT_U32:
	case LXCAN_DPT_FORMAT_V32:
		resultValue = (T)((unsigned long)dptOriginValue[0] << 24);
		resultValue += (T)((unsigned long)dptOriginValue[1] << 16);
		resultValue += (T)((unsigned long)dptOriginValue[2] << 8);
		resultValue += (T)(dptOriginValue[3]);
		return LXCAN_DEVICE_OK;
		//		break;

	case LXCAN_DPT_FORMAT_F16 :
		{
			// Get the DPT sign, mantissa and exponent
			int signMultiplier = (dptOriginValue[0] & 0x80) ? -1 : 1;
			uint16_t absoluteMantissa = dptOriginValue[1] + ((dptOriginValue[0]&0x07)<<8);
			if (signMultiplier == -1) 
			{ // Calculate absolute mantissa value in case of negative mantissa
				// Abs = 2's complement + 1
				absoluteMantissa = ((~absoluteMantissa)& 0x07FF ) + 1;
			}
			uint8_t exponent = (dptOriginValue[0]&0x78)>>3;
			resultValue = (T)(0.01 * ((long)absoluteMantissa << exponent) * signMultiplier);
			return LXCAN_DEVICE_OK;
		}
		//		break;

	case LXCAN_DPT_FORMAT_F32 :
		return LXCAN_DEVICE_NOT_IMPLEMENTED;
		//		break;

		//	default : LXCAN_DEVICE_ERROR;
	}
	return LXCAN_DEVICE_ERROR;
}



template <typename T>
e_LXCanDeviceStatus LXCanObject::value_write(T originValue)
{
	uint8_t *dptDestValue = value_buff;
	uint8_t dptFormat = LXCanDPTIdToFormat[Dpt_ID];
	switch (dptFormat)
	{
	case LXCAN_DPT_FORMAT_B1:
	case LXCAN_DPT_FORMAT_B2:
	case LXCAN_DPT_FORMAT_B1U3:
	case LXCAN_DPT_FORMAT_A8:
	case LXCAN_DPT_FORMAT_U8:
	case LXCAN_DPT_FORMAT_V8:
	case LXCAN_DPT_FORMAT_B5N3:
		dptDestValue[0] = (uint8_t)(originValue);
		return LXCAN_DEVICE_OK;
	case LXCAN_DPT_FORMAT_U16:
	case LXCAN_DPT_FORMAT_V16:
		dptDestValue[0] = (uint8_t)((unsigned int)originValue>>8);
		dptDestValue[1] = (uint8_t)(originValue);
		return LXCAN_DEVICE_OK;
		//		break;

	case LXCAN_DPT_FORMAT_U32:
	case LXCAN_DPT_FORMAT_V32:
		dptDestValue[0] = (uint8_t)((unsigned long)originValue>>24);
		dptDestValue[1] = (uint8_t)((unsigned long)originValue>>16);
		dptDestValue[2] = (uint8_t)((unsigned long)originValue>>8);
		dptDestValue[3] = (uint8_t)(originValue);
		return LXCAN_DEVICE_OK;
		//		break;

	case LXCAN_DPT_FORMAT_F16 :
		{
			long longValuex100 = (long)(100.0 * originValue);
			bool negativeSign = (longValuex100 & 0x80000000)? true : false;
			uint8_t exponent = 0;
			uint8_t round = 0;

			if (negativeSign)
			{
				while(longValuex100 < (long)(-2048)) 
				{
					exponent++; round = (uint8_t)(longValuex100) & 1 ; longValuex100>>=1; longValuex100|=0x80000000;
				}
			}
			else
			{
				while(longValuex100 > (long)(2047)) 
				{
					exponent++; round = (uint8_t)(longValuex100) & 1 ; longValuex100>>=1;
				}

			}
			if (round) longValuex100++;
			dptDestValue[1] = (uint8_t)longValuex100;
			dptDestValue[0] = (uint8_t)(longValuex100>>8) & 0x7 ;
			dptDestValue[0] += exponent<<3;
			if (negativeSign) dptDestValue[0] += 0x80;
			return LXCAN_DEVICE_OK;
		}
		//		break;

	case LXCAN_DPT_FORMAT_F32 :
		return LXCAN_DEVICE_NOT_IMPLEMENTED;
		//		break;

		//	default : LXCAN_DEVICE_ERROR;
	}
	return LXCAN_DEVICE_ERROR;
}



template e_LXCanDeviceStatus LXCanObject::value_read <unsigned char>( unsigned char&);
template e_LXCanDeviceStatus LXCanObject::value_read <char>( char&);
template e_LXCanDeviceStatus LXCanObject::value_read <unsigned short>( unsigned short& );
template e_LXCanDeviceStatus LXCanObject::value_read <unsigned int>( unsigned int& );
template e_LXCanDeviceStatus LXCanObject::value_read <int>( int& );
template e_LXCanDeviceStatus LXCanObject::value_read <unsigned long>( unsigned long& );
template e_LXCanDeviceStatus LXCanObject::value_read <long>( long& );
template e_LXCanDeviceStatus LXCanObject::value_read <float>( float& );
template e_LXCanDeviceStatus LXCanObject::value_read <double>( double& );

template e_LXCanDeviceStatus LXCanObject::value_write <unsigned char>(unsigned char );
template e_LXCanDeviceStatus LXCanObject::value_write <char>(char );
template e_LXCanDeviceStatus LXCanObject::value_write <unsigned short>(unsigned short );
template e_LXCanDeviceStatus LXCanObject::value_write <unsigned int>(unsigned int );
template e_LXCanDeviceStatus LXCanObject::value_write <int>(int );
template e_LXCanDeviceStatus LXCanObject::value_write <unsigned long>(unsigned long );
template e_LXCanDeviceStatus LXCanObject::value_write <long>(long );
template e_LXCanDeviceStatus LXCanObject::value_write <float>(float );
template e_LXCanDeviceStatus LXCanObject::value_write <double>(double );

#ifdef DEBUG

void dataTobin1(uint32_t data)
{
	char* str_temp = "|31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|\n";
	char str_bin[] = "|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |\n";
	for(uint8_t i=0 ; i<32 ; i++)
	{
		if(0x01 & (data >> i))
			str_bin[95-3*i] = '1';
		else
			str_bin[95-3*i] = '0';
	}
	uart1.printf("Data Hex:%x\n",data);
	uart1.put_string(str_temp);
	uart1.put_string(str_bin);
	uart1.printf("\n");
	//LXCan_log_d("Tset","DATA HEX:%X,Bin:%s",data,str_bin);
}
uint8_t test1(uint8_t* data)
{
	LXCan_log_d("OBJECT_callback","data:%x,%x,%x",data[0],data[1],data[2]);
	return 1;
}
uint8_t test2(uint8_t* data)
{
	LXCan_log_d("OBJECT_callback2","data:%x,%x,%x",data[0],data[1],data[2]);
	return 1;
}
void object_test()
{
	LXCanObject object_t;
	LXCanObject object_t2;
	object_t.dpt_write(LXCAN_DPT_7_001);
	LXCan_log_d("OBJECT_TEST","dpt_id:%d",object_t.dpt_read());
	unsigned long temp = 0x12345678;
	object_t.value_write(temp);
	unsigned long temp1;
	object_t.value_read(temp1);
	LXCan_log_d("OBJECT_TEST","value:%x",temp1);
	uint8_t temp2[4];
	uint8_t temp2_len;
	object_t.value_read(temp2,temp2_len);
	LXCan_log_d("OBJECT_TEST","value:%x,%x,%x,%x",temp2[0],temp2[1],temp2[2],temp2[3]);
	object_t.Transimit_write(LXCan_ENABLE);
	LXCan_log_d("OBJECT_TEST","Transimi:%x",object_t.Transimit_read());
	dataTobin1((uint32_t)object_t.config_read());
	LXCan_log_d("OBJECT_TEST","leng:%d",object_t.length_read());
	
	for(uint8_t i=0; i<OBJECT_REGISTER_SIZE ; i++)
		object_t.register_write(i,0xA0+i);

	LXCan_log_d("OBJECT_TEST","reg:");
	for (int i = 0; i < OBJECT_REGISTER_SIZE; i++)
	{
		uart1.printf("%x,",object_t.register_read(i));
	}
	uart1.printf("\n");

	unsigned char str[] = {1,2,3};
	object_t.callback[0].attach(test1);
	object_t.callback[1].attach(test2);
	object_t.callback[0].call((uint8_t*)str);
	
	object_t.callback[1].call((uint8_t*)str);
	
	

}
#endif

